<?php


namespace App\Service;


use App\Model\Device;
use App\Utils\Logger;
use Carbon\Carbon;
use App\Model\Normal;
use Hyperf\Redis\Redis;
use Hyperf\Utils\ApplicationContext;
use Psr\Container\ContainerInterface;
use Hyperf\Di\Annotation\Inject;

class DeviceMqttService
{
    /**
     * @Inject
     * @var ContainerInterface
     */
    protected $container;
    protected Redis $redis;


    public function __construct()
    {
        $this->redis = ApplicationContext::getContainer()->get(Redis::class);
    }

    public function subscribe($message, $topic)
    {
        $mac = substr($message, 5, 12);
        $id = substr($message, 17, 2);
//        go(function () use ($mac, $id) {
//            Normal::logger('id消息: ' . $mac . '---' . $id, 'order-queue');
//        });
        switch ($id) {
            case '0B':
                // 心跳
                $this->heartbeat($message, $topic);
                $tick = substr($message, 19, 4);
                $content = $mac . "0B" . "00" . $tick;
                return $this->returnData($content);
            case '0A':
                $this->rechargeCallback($message);
                break;
            case '0C':
                $this->statusQuery($message);
                break;
            case '0D':
                $this->statusCallback($message);
                break;
            case '03':
                $this->restartCallback($message);
                break;
            case '10':
                return $this->bleConnectStatus($message);
                break;
            case '02':
                $this->querySpeed($message);
                break;
            case '09':
                $this->makeFg($message);
                break;
            case '07':
                $utcClass= time();
                $utcClass += 8*3600;
                $utc = strtoupper(dechex($utcClass));
                $utc = $this->toLen($utc, 8);
                $content = $mac . "07" . "00" . $utc;
                return $this->returnData($content);
            case '05':
                // 心跳
                $this->newheartbeat($message, $topic);
                $tick = substr($message, 19, 4);
                $content = $mac . "05" . "00" . $tick;
                return $this->returnData($content);
        }
        //var_dump($mac, $id);
    }

    # 心跳
    public function heartbeat($message, $topic)
    {
        $mac = substr($message, 5, 12);
        $id = substr($message, 17, 2);

        // 主表
        # 心跳编号，回复需带上
        $tick = hexdec(substr($message, 19, 4));

        $iccid = (string)substr($message, 23, 40);
        $iccid = hex2bin($iccid);
        # 4G网络信息 20-33 强，10-20 中，10以下差, 99无信号
        $signal = hexdec(substr($message, 63, 2));
        # 电量
        $hexString = substr($message, 65, 8);
        // 将十六进制字符串转换为无符号整数
        $unsignedInt = hexdec($hexString);
        // 如果最高位为1，表示负数，需要进行符号位处理
        // 首先确定最高位的值（这里假设最高位在十六进制的最左边）
        $mask = 0x80000000;

        // 使用位与运算符检查最高位
        if ($unsignedInt &$mask) {
            // 最高位为1，表示有符号整数中的负数
            // 转换为有符号整数
            $du =$unsignedInt - 0x100000000;
        } else {
            // 最高位为0，表示正数
            $du =$unsignedInt;
        }


        # 总电量
        $total = hexdec(substr($message, 73, 8));
        # 总功率
        $w = hexdec(substr($message, 81, 8));
        # 状态
        $status = hexdec(substr($message, 89, 2));

        // 运行状态 0正常，1过载
        $emsStatus = hexdec(substr($message, 91, 2));

        // 从表
        $sMac = substr($message, 93, 12);

        # 电量
        // $sDu = hexdec(substr($message, 105, 8));

        # 电量
        $hexString = substr($message, 105, 8);
        // 将十六进制字符串转换为无符号整数
        $unsignedInt = hexdec($hexString);
        // 如果最高位为1，表示负数，需要进行符号位处理
        // 首先确定最高位的值（这里假设最高位在十六进制的最左边）
        $mask = 0x80000000;

        // 使用位与运算符检查最高位
        if ($unsignedInt &$mask) {
            // 最高位为1，表示有符号整数中的负数
            // 转换为有符号整数
            $sDu =$unsignedInt - 0x100000000;
        } else {
            // 最高位为0，表示正数
            $sDu =$unsignedInt;
        }

        # 总电量
        $sTotal = hexdec(substr($message, 113, 8));
        # 总功率
        $sW = hexdec(substr($message, 121, 8));
        # 状态
        $sStatus = hexdec(substr($message, 129, 2));
        # 从表运行状态
        $sEmsStatus = hexdec(substr($message, 131, 2));

        $device = Device::where('mac', $mac)->first();
        //  $devicePowerLogService = $this->container->get(DevicePowerLogService::class);
        //    $driver = $this->container->get(DriverFactory::class)->get('heart_power');
        if ($device) {
            $tempTotal = $device->total;
            $xh = ($total > 0 ? $total : 0) - ($device->total*1000);
            $device->signal = $signal;
            $device->du = $du != 0 ? $du / 1000 : 0;
            $device->total = $total > 0 ? $total / 1000 : 0;
            $device->status = $status;
            $device->power = $w > 0 ? $w / 1000 : 0;
            $device->netType = 1;
            $device->clientId = $topic;
            $device->readAt = Carbon::now()->toDateTimeString();
            $device->onlineStatus = 1;
            $device->emsStatus = $emsStatus;
            $device->iccid = $iccid;
            $device->is_master = 1;
            $device->m_mac = '';
            $device->save();

            if($tempTotal > 0){
                $this->addXh($device->id,$xh);
            }

//            $data['deviceId'] = $device->id;
//            $data['du'] = $du;
//            $data['total'] = $total;
//            $data['w'] = $w;
//            $data['xh'] = $xh;
//            $data['volt'] = 0;
//            $data['child_volt'] = 0;
//            $data['curr'] = 0;
//            $data['child_curr'] = 0;
//            $data['signal'] = $signal;
//            $cacheKey = 'sub_log_cache'.$device->id;
//            $lockAcquired = $this->redis->set($cacheKey, 1, ['NX', 'EX' => 900]);
//            if ($lockAcquired) {
//                $driver->push(new HeartPowerJob(json_encode($data)));
//            }
            # 电表日志
//            $devicePowerLogService->update($device->id, $du, $total, $w, $xh,$signal);
        } else {
            Logger::get()->error('device not found', [$mac]);
        }

        if ($sMac && $sMac !== '000000000000') {
            if($sDu == 0 && $sTotal == 0 && $sW == 0 && $sStatus ==0 && $sEmsStatus == 0 ){
                Normal::logger('0b从表无效报文：'.$message,'order-queue');
                return;
            }
            $sDevice = Device::where('mac', $sMac)->first();
            $stempTotal = $sDevice->total;
            if (!$sDevice) {
                Logger::get()->error('device not found', [$sMac]);
                return;
            }
            // if ($sDevice->isMaster) {
            //     return;
            // }
            $sDevice->is_master = 0;
            $xh = ($sTotal > 0 ? $sTotal: 0) - ($sDevice->total*1000);
            $sDevice->signal = $signal;
            $sDevice->du = $sDu != 0 ? $sDu / 1000 : 0;
            $sDevice->total = $sTotal > 0 ? $sTotal / 1000 : 0;
            $sDevice->status = $sStatus;
            $sDevice->power = $sW > 0 ? $sW / 1000 : 0;
            $sDevice->netType = 1;
            $sDevice->mMac = $mac;
            $sDevice->clientId = $topic;
            $sDevice->readAt = Carbon::now()->toDateTimeString();
            $sDevice->online_status = 1;
            $sDevice->emsStatus = $sEmsStatus;
            $sDevice->save();

            if($stempTotal > 0){
                $this->addXh($sDevice->id,$xh);
            }

//            $data['deviceId'] = $sDevice->id;
//            $data['du'] = $sDu;
//            $data['total'] = $sTotal;
//            $data['w'] = $sW;
//            $data['xh'] = $xh;
//            $data['volt'] = 0;
//            $data['child_volt'] = 0;
//            $data['curr'] = 0;
//            $data['child_curr'] = 0;
//            $data['signal'] = $signal;
//            $cacheKey = 'sub_log_cache'.$sDevice->id;
//            $lockAcquired = $this->redis->set($cacheKey, 1, ['NX', 'EX' => 900]);
//            if ($lockAcquired) {
//                $driver->push(new HeartPowerJob(json_encode($data)));
//            }
            # 电表日志
//            $devicePowerLogService->update($sDevice->id, $sDu, $sTotal, $sW, $xh,$signal);
        }
    }

    public function addXh($deviceId,$xh){

        if ($xh <= 0) return;

        $time = time();
        $this->redis->select(2);
        // 维持原有Key命名规则
        $keys = [
            'zhufang_database_' . $deviceId . '-' . date('YmdH', $time), // 小时级
            'zhufang_database_' . $deviceId . '-' . date('Ymd', $time),   // 天级
            'zhufang_database_' . $deviceId . '-' . date('Ym', $time)     // 月级
        ];

        // 使用Pipeline批量操作
        $pipe = $this->redis->pipeline();
        foreach ($keys as $i => $key) {
            $pipe->incrBy($key, $xh);
            // 根据Key类型设置不同TTL
            $pipe->expire($key,
                $i === 0 ? 7776000 :    // 第一个Key是小时级，90天（3600*24*90）
                    63072000                // 其余为天级和月级，730天（3600*24*730）
            );
        }
        $pipe->exec();



//        if($xh <= 0){
//            return '';
//        }else{
//            $xh = (int)$xh;
//        }
//
//        $time = time();
//        $hourKey = 'zhufang_database_' . $deviceId . '-' . date('YmdH', $time);
//        $dayKey = 'zhufang_database_' . $deviceId . '-' . date('Ymd', $time);
//        $monthKey = 'zhufang_database_' . $deviceId . '-' . date('Ym', $time);
//        $this->redis->select(2);
//        if ($this->redis->exists($hourKey)) {
//            if ($xh > 0) {
//                $this->redis->incrBy($hourKey, $xh);
//            }
//        } else {
//            if ($xh > 0) {
//                $this->redis->setex($hourKey, 3600 * 24 * 90, $xh);
//            }
//        }
//        if ($this->redis->exists($dayKey)) {
//            if ($xh > 0) {
//                $this->redis->incrBy($dayKey, $xh);
//            }
//        } else {
//            if ($xh > 0) {
//                $this->redis->setex($dayKey, 3600 * 24 * 730, $xh);
//            }
//        }
//        if ($this->redis->exists($monthKey)) {
//            if ($xh > 0) {
//                $this->redis->incrBy($monthKey, $xh);
//            }
//        } else {
//            if ($xh > 0) {
//                $this->redis->setex($monthKey, 3600 * 24 * 730, $xh);
//            }
//        }


    }

    # 心跳
    public function newheartbeat($message, $topic)
    {
        $mac = substr($message, 5, 12);
        $id = substr($message, 17, 2);

        // 主表
        # 心跳编号，回复需带上
        $tick = hexdec(substr($message, 19, 4));

        $iccid = (string)substr($message, 23, 40);
        $iccid = hex2bin($iccid);
        # 4G网络信息 20-33 强，10-20 中，10以下差, 99无信号
        $signal = hexdec(substr($message, 63, 2));
        # 电量
        $hexString = substr($message, 65, 8);
        $unsignedInt = hexdec($hexString);
        // 如果最高位为1，表示负数，需要进行符号位处理
        // 首先确定最高位的值（这里假设最高位在十六进制的最左边）
        $mask = 0x80000000;

        // 使用位与运算符检查最高位
        if ($unsignedInt &$mask) {
            // 最高位为1，表示有符号整数中的负数
            // 转换为有符号整数
            $du =$unsignedInt - 0x100000000;
        } else {
            // 最高位为0，表示正数
            $du =$unsignedInt;
        }
        # 总电量
        $total = hexdec(substr($message, 73, 8));
        # 总功率
        $w = hexdec(substr($message, 81, 8));
        # 状态
        $status = hexdec(substr($message, 89, 2));

        // 运行状态 0正常，1过载
        $emsStatus = hexdec(substr($message, 91, 2));

        $volt =  hexdec(substr($message, 93, 8));

        $curr =  hexdec(substr($message, 101, 8));
        // 从表
        $sMac = substr($message, 109, 12);

        # 电量
        $hexString = substr($message, 121, 8);
        $unsignedInt = hexdec($hexString);
        // 如果最高位为1，表示负数，需要进行符号位处理
        // 首先确定最高位的值（这里假设最高位在十六进制的最左边）
        $mask = 0x80000000;

        // 使用位与运算符检查最高位
        if ($unsignedInt &$mask) {
            // 最高位为1，表示有符号整数中的负数
            // 转换为有符号整数
            $sDu =$unsignedInt - 0x100000000;
        } else {
            // 最高位为0，表示正数
            $sDu =$unsignedInt;
        }
        # 总电量
        $sTotal = hexdec(substr($message, 129, 8));
        # 总功率
        $sW = hexdec(substr($message, 137, 8));
        # 状态
        $sStatus = hexdec(substr($message, 145, 2));
        # 从表运行状态
        $sEmsStatus = hexdec(substr($message, 147, 2));

        $child_volt =  hexdec(substr($message, 149, 8));

        $child_curr=  hexdec(substr($message, 157, 8));

        try{
            $device = Device::where('mac', $mac)->first();
            //        $driver = $this->container->get(DriverFactory::class)->get('heart_power');
            if ($device) {
                $tempTotal = $device->total;
                $xh = ($total > 0 ? $total:0) - ($device->total*1000);
                $device->signal = $signal;
                $device->du = $du != 0 ? $du / 1000 : 0;
                $device->total = $total > 0 ? $total / 1000 : 0;
                $device->status = $status;
                $device->power = $w > 0 ? $w / 1000 : 0;
                $device->netType = 1;
                $device->clientId = $topic;
                $device->readAt = Carbon::now()->toDateTimeString();
                $device->onlineStatus = 1;
                $device->emsStatus = $emsStatus;
                $device->iccid = $iccid;
                $device->is_master = 1;
                $device->m_mac = '';
                if($volt){
                    $device->volt = round($volt/1000,2);
                }else{
                    $device->volt = 0;
                }
                if($curr){
                    $device->curr  = round($curr/1000,2);
                }else{
                    $device->curr  = 0;
                }
                // }
                $device->save();
                if($tempTotal > 0) {
                    $this->addXh($device->id, $xh);
                }
//                $data['deviceId'] = $device->id;
//                $data['du'] = $du;
//                $data['total'] = $total;
//                $data['w'] = $w;
//                $data['xh'] = $xh;
//                $data['volt'] = $volt;
//                $data['child_volt'] = $child_volt;
//                $data['curr'] = $curr;
//                $data['child_curr'] = $child_curr;
//                $data['signal'] = $signal;
//                $cacheKey = 'sub_log_cache'.$device->id;
//                $lockAcquired = $this->redis->set($cacheKey, 1, ['NX', 'EX' => 900]);
//                if ($lockAcquired) {
//                    $driver->push(new HeartPowerJob(json_encode($data)));
//                }
                # 电表日志
                //      $devicePowerLogService->update($device->id, $du, $total, $w, $xh,$volt,$child_volt,$curr,$child_curr,$signal);
            } else {
                Logger::get()->error('device not found', [$mac]);
            }

            if ($sMac && $sMac !== '000000000000') {
                if($sDu == 0 && $sTotal == 0 && $sW == 0 && $sStatus ==0 && $sEmsStatus == 0 ){
                    Normal::logger('05从表无效报文：'.$message,'order-queue');
                    return;
                }
//                Logger::get('mqtt')->notice('mqtt data', [$sMac, $sStatus, $sDu, $sTotal, $sW, $signal]);
                $sDevice = Device::where('mac', $sMac)->first();
                if (!$sDevice) {
                    Logger::get()->error('device not found', [$sMac]);
                    return;
                }
                $stempTotal = $sDevice->total;
                if ($sDevice->isMaster) {
                    return;
                }
                $sDevice->is_master = 0;
                $xh = ($sTotal > 0 ? $sTotal : 0) - ($sDevice->total*1000);
                $sDevice->signal = $signal;
                $sDevice->du = $sDu != 0 ? $sDu / 1000 : 0;
                $sDevice->total = $sTotal > 0 ? $sTotal / 1000 : 0;
                $sDevice->status = $sStatus;
                $sDevice->power = $sW > 0 ? $sW / 1000 : 0;
                $sDevice->netType = 1;
                $sDevice->mMac = $mac;
                $sDevice->clientId = $topic;
                $sDevice->readAt = Carbon::now()->toDateTimeString();
                $sDevice->online_status = 1;
                $sDevice->emsStatus = $sEmsStatus;
                if($child_volt){
                    $sDevice->volt = round($child_volt/1000,2);
                    $sDevice->curr = round($sW/$child_volt,2);
                }else{
                    $sDevice->volt = 0;
                    $sDevice->curr = 0;

                }
                $sDevice->save();
                if($stempTotal > 0) {
                    $this->addXh($sDevice->id, $xh);
                }
//                $data['deviceId'] = $sDevice->id;
//                $data['du'] = $sDu;
//                $data['total'] = $sTotal;
//                $data['w'] = $sW;
//                $data['xh'] = $xh;
//                $data['volt'] = $volt;
//                $data['child_volt'] = $child_volt;
//                $data['curr'] = $curr;
//                $data['child_curr'] = $child_curr;
//                $data['signal'] = $signal;
//                $cacheKey = 'sub_log_cache'.$sDevice->id;
//                $lockAcquired = $this->redis->set($cacheKey, 1, ['NX', 'EX' => 900]);
//                if ($lockAcquired) {
//                    $driver->push(new HeartPowerJob(json_encode($data)));
//                }
                # 电表日志
                // $devicePowerLogService->update($sDevice->id, $sDu, $sTotal, $sW, $xh,$volt,$child_volt,$curr,$child_curr,$signal);
            }
        }catch (\Exception $e){
            Normal::logger('heartbeat-----' ,$e->getMessage().$e->getTraceAsString(), 'order-queue');
        }
    }

    # 状态查询
    public function statusQuery($message)
    {
        $mac = substr($message, 5, 12);
        $id = substr($message, 17, 2);

        $acku = substr($message, 19, 2);
        if ($acku != '00') {
            return;
        }
        # 电量
        $du = hexdec(substr($message, 21, 8));
        $unsignedInt = $du;
        // 如果最高位为1，表示负数，需要进行符号位处理
        // 首先确定最高位的值（这里假设最高位在十六进制的最左边）
        $mask = 0x80000000;

        // 使用位与运算符检查最高位
        if ($unsignedInt &$mask) {
            // 最高位为1，表示有符号整数中的负数
            // 转换为有符号整数
            $du =$unsignedInt - 0x100000000;
        } else {
            // 最高位为0，表示正数
            $du =$unsignedInt;
        }

        # 总电量
        $total = hexdec(substr($message, 29, 8));
        # 总功率
        $w = hexdec(substr($message, 37, 8));
        # 状态
        $status = hexdec(substr($message, 45, 2));
        # 过载状态
        $emsStatus = hexdec(substr($message, 47, 2));

        $device = Device::where('mac', $mac)->first();
        if ($device) {
            $device->du = $du != 0 ? $du / 1000 : 0;
            $device->total = $total > 0 ? $total / 1000 : 0;
            $device->status = $status;
            $device->power = $w > 0 ? $w / 1000 : 0;
            $device->readAt = Carbon::now()->toDateTimeString();
            $device->onlineStatus = 1;
            $device->emsStatus = $emsStatus;
            $device->save();
        }
    }

    # 充值回调
    public function rechargeCallback($message)
    {
        $mac = substr($message, 5, 12);
        $id = substr($message, 17, 2);
        $opt = substr($message,19,2);
        # 剩余电量
        $du = substr($message, 23, 8);
        //新增
        $unsignedInt = hexdec($du);
        // 如果最高位为1，表示负数，需要进行符号位处理
        // 首先确定最高位的值（这里假设最高位在十六进制的最左边）
        $mask = 0x80000000;

        // 使用位与运算符检查最高位
        if ($unsignedInt &$mask) {
            // 最高位为1，表示有符号整数中的负数
            // 转换为有符号整数
            $du =$unsignedInt - 0x100000000;
        } else {
            // 最高位为0，表示正数
            $du =$unsignedInt;
        }
        # log
        // Logger::get('mqtt')->notice('充值成功', [$mac, $du, $message]);
        try{
            $device = Device::where('mac', $mac)->first();
            if ($device) {
                $device->du = $du != 0 ? $du / 1000 : 0;
                //$device->readAt = Carbon::now()->toDateTimeString();
                $device->recharge_callback_at = Carbon::now()->toDateTimeString();
                $device->save();
                Normal::logger('设备mac' .$mac . '度数' . $du. 'message:'.$message, 'order-queue', 'info');
            }
        }catch (\Exception $e){
            Normal::logger('设备充值异常mac' .$mac . '度数' . $du. 'message:'.$message.$e->getMessage(), 'order-queue', 'info');
        }
    }

    # 重启回调
    public function restartCallback($message)
    {
        // +00098A9AEA016B430D0002D5
        $mac = substr($message, 5, 12);
        $id = substr($message, 17, 2);

        # 状态
        $acku= hexdec(substr($message, 19, 2));

        $device = Device::where('mac', $mac)->first();
        if ($device) {
            $device->save();
        }
    }

    public function makeFg($message){
        $mac = substr($message, 5, 12);
        $id = substr($message, 17, 2);
        $acku =  hexdec(substr($message, 19, 2));
        if($acku <= 0){
            $device = Device::where('mac', $mac)->first();
            $device->coef_callback_at =Carbon::now()->toDateTimeString();
            $device->save();
        }
    }

    # 拉合闸回调
    public function statusCallback($message)
    {
        // +00098A9AEA016B430D0002D5
        $mac = substr($message, 5, 12);
        $id = substr($message, 17, 2);

        # 状态
        $status = hexdec(substr($message, 21, 2));

        $device = Device::where('mac', $mac)->first();
        if ($device) {
            $device->status = $status;
            $device->readAt = Carbon::now()->toDateTimeString();
            $device->save();
        }
    }

    # 从设备连接状态
    public function bleConnectStatus($message)
    {
        $cache = $this->container->get(\Psr\SimpleCache\CacheInterface::class);
        $mac = substr($message, 5, 12);
        $id = substr($message, 17, 2);
        $opt = substr($message, 19, 2);
        $state = substr($message, 23, 2);

        if ($opt == '02' OR $opt == '01') {
            Logger::get()->notice('slave device connect state', [$message, $opt, $state]);
            $cache->set($mac, $state, 10);
        }
        # 从表上报
        if ($opt == '04') {
            $sId = substr($message, 23, 2);
            Logger::get()->notice('slave device report1', [$message, $id, $opt, $sId]);
            # 拉闸合闸上报
            if ($sId == '0D') {
                $status = substr($message, 27, 2);
                Logger::get()->notice('slave device report2', [$message, $opt, $sId, $status]);
                $device = Device::where('mac', $mac)->first();
                if ($device) {
                    $device->status = $status;
                    $device->readAt = Carbon::now()->toDateTimeString();
                    $device->save();
                }
            }
            if ($sId == '02') {
                $speed = hexdec(substr($message, 29, 8));
                Logger::get()->notice('slave device report2', [$message, $opt, $sId,substr($message, 29, 8), $speed]);
                $device = Device::where('mac', $mac)->first();
                $opt1 = substr($message, 25, 2);
                if ($device) {
                    if($opt1 == '03'){
                        $device->speed = $speed;
                    }
                    // if($opt1 == '02'){
                    //     $device->pay_mode = $device->pay_type = hexdec(substr($message, 29, 2));
                    //     $device->alias = 'bleConnectStatus';
                    // }
                    // $device->speed = $speed;
                    $device->read_speed_at = Carbon::now()->toDateTimeString();
                    $device->save();
                }
            }
            if ($sId == '0A') {
                $du = substr($message, 29, 8);
                $unsignedInt = hexdec($du);
                // 如果最高位为1，表示负数，需要进行符号位处理
                // 首先确定最高位的值（这里假设最高位在十六进制的最左边）
                $mask = 0x80000000;

                // 使用位与运算符检查最高位
                if ($unsignedInt &$mask) {
                    // 最高位为1，表示有符号整数中的负数
                    // 转换为有符号整数
                    $du =$unsignedInt - 0x100000000;
                } else {
                    // 最高位为0，表示正数
                    $du =$unsignedInt;
                }
                $device = Device::where('mac', $mac)->first();
                // Logger::get('mqtt')->notice('充值成功', [$mac, $du, $message]);
                if ($device) {
                    $device->du = $du != 0 ? $du / 1000:0;
                    //$device->readAt = Carbon::now()->toDateTimeString();
                    $device->recharge_callback_at = Carbon::now()->toDateTimeString();
                    $device->save();
                    Normal::logger('设备mac' .$mac . '度数' . $du. 'message:'.$message, 'order-queue', 'info');
                }
            }
            $cache->set($mac . '-close', 1, 30);
            return $this->returnData($mac . "10" . "00");
        }
        return null;
    }

    # 读计量系数
    public function querySpeed($message)
    {
        $mac = substr($message, 5, 12);
        $id = substr($message, 17, 2);
        $opt = substr($message, 19, 2);
        $speed = hexdec(substr($message, 23, 8));
        Logger::get()->notice('speed', [$message, substr($message, 21, 8), $speed]);

        $device = Device::where('mac', $mac)->first();
        if ($device) {
            if($speed > 30){
                $device->speed = $speed;
            }
            if($opt == '02'){
                $device->pay_mode = $device->pay_type = hexdec(substr($message, 23, 2));;
            }
            $device->read_speed_at = Carbon::now()->toDateTimeString();
            $device->save();
        }
    }

    public function returnData($content): string
    {
        return ":" . $this->toLen( strtoupper( dechex( ( strlen($content) / 2 ) ) ) ) . $content . '00' . "\r\n";
    }

    public function returnData1($content): string
    {
        return ":" . $this->toLen( strtoupper( dechex( ( strlen($content) / 2 ) ) ) ) . $content . "\r\n";
    }

    public function toLen($l, $t = 4)
    {
        $len = strlen($l);
        if (strlen($l) < $t) {
            for ($i = 0; $i < ($t - $len); $i ++) {
                $l = '0' . $l;
            }
        }
        return $l;
    }

    public function reverseMac($mac)
    {
        $newMac = substr($mac, 10, 2) . substr($mac, 8, 2) .
            substr($mac, 6, 2). substr($mac, 4, 2) . substr($mac, 2, 2) .
            substr($mac, 0, 2);
        Logger::get()->notice('new mac', [$newMac]);
        return $newMac;
    }
}
